package com.white.progressview;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ProgressBar;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Shader;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Author White
 * Date 2017/4/23
 * Time 14:38
 */
public class CircleProgressView extends ProgressBar {
    /**
     * * The constant CircleProgressView_progressNormalColor
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSNORMALCOLOR = "progressNormalColor";
    /**
     * * The constant CircleProgressView_progressReachColor
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSREACHCOLOR = "progressReachColor";
    /**
     * * The constant CircleProgressView_progressTextColor
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSTEXTCOLOR = "progressTextColor";
    /**
     * * The constant CircleProgressView_progressTextSize
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSTEXTSIZE = "progressTextSize";
    /**
     * * The constant CircleProgressView_progressTextOffset
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSTEXTOFFSET = "progressTextOffset";
    /**
     * * The constant CircleProgressView_progressNormalSize
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSNORMALSIZE = "progressNormalSize";
    /**
     * * The constant CircleProgressView_progressReachSize
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSREACHSIZE = "progressReachSize";
    /**
     * * The constant CircleProgressView_radius
     */
    public static final String CIRCLEPROGRESSVIEW_RADIUS = "radius";
    /**
     * * The constant CircleProgressView_progressTextVisible
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSTEXTVISIBLE = "progressTextVisible";
    /**
     * * The constant CircleProgressView_progressStartArc
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSSTARTARC = "progressStartArc";
    /**
     * * The constant CircleProgressView_progressTextSkewX
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSTEXTSKEWX = "progressTextSkewX";
    /**
     * * The constant CircleProgressView_progressTextPrefix
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSTEXTPREFIX = "progressTextPrefix";
    /**
     * * The constant CircleProgressView_progressTextSuffix
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSTEXTSUFFIX = "progressTextSuffix";
    /**
     * * The constant CircleProgressView_innerBackgroundColor
     */
    public static final String CIRCLEPROGRESSVIEW_INNERBACKGROUNDCOLOR = "innerBackgroundColor";
    /**
     * * The constant CircleProgressView_progressStyle
     */
    public static final String CIRCLEPROGRESSVIEW_PROGRESSSTYLE = "progressStyle";
    /**
     * * The constant CircleProgressView_innerProgressColor
     */
    public static final String CIRCLEPROGRESSVIEW_INNERPROGRESSCOLOR = "innerProgressColor";
    /**
     * * The constant CircleProgressView_innerPadding
     */
    public static final String CIRCLEPROGRESSVIEW_INNERPADDING = "innerPadding";
    /**
     * * The constant CircleProgressView_outerColor
     */
    public static final String CIRCLEPROGRESSVIEW_OUTERCOLOR = "outerColor";
    /**
     * * The constant CircleProgressView_outerSize
     */
    public static final String CIRCLEPROGRESSVIEW_OUTERSIZE = "outerSize";
    /**
     * * The constant CircleProgressView_reachCapRound
     */
    public static final String CIRCLEPROGRESSVIEW_REACHCAPROUND = "reachCapRound";
    /**
     * * The constant PROGRESS_STYLE_NORMAL
     */
    private static final int PROGRESS_STYLE_NORMAL = 0;
    /**
     * * The constant PROGRESS_STYLE_FILL_IN
     */
    private static final int PROGRESS_STYLE_FILL_IN = 1;
    /**
     * * The constant PROGRESS_STYLE_FILL_IN_ARC
     */
    private static final int PROGRESS_STYLE_FILL_IN_ARC = 2;
    /**
     * * The constant STATE
     */
    private static final String STATE = "state";
    /**
     * * The constant PROGRESS_STYLE
     */
    private static final String PROGRESS_STYLE = "progressStyle";
    /**
     * * The constant TEXT_COLOR
     */
    private static final String TEXT_COLOR = "textColor";
    /**
     * * The constant TEXT_SIZE
     */
    private static final String TEXT_SIZE = "textSize";
    /**
     * * The constant TEXT_SKEW_X
     */
    private static final String TEXT_SKEW_X = "textSkewX";
    /**
     * * The constant TEXT_VISIBLE
     */
    private static final String TEXT_VISIBLE = "textVisible";
    /**
     * * The constant TEXT_SUFFIX
     */
    private static final String TEXT_SUFFIX = "textSuffix";
    /**
     * * The constant TEXT_PREFIX
     */
    private static final String TEXT_PREFIX = "textPrefix";
    /**
     * * The constant REACH_BAR_COLOR
     */
    private static final String REACH_BAR_COLOR = "reachBarColor";
    /**
     * * The constant REACH_BAR_SIZE
     */
    private static final String REACH_BAR_SIZE = "reachBarSize";
    /**
     * * The constant NORMAL_BAR_COLOR
     */
    private static final String NORMAL_BAR_COLOR = "normalBarColor";
    /**
     * * The constant NORMAL_BAR_SIZE
     */
    private static final String NORMAL_BAR_SIZE = "normalBarSize";
    /**
     * * The constant IS_REACH_CAP_ROUND
     */
    private static final String IS_REACH_CAP_ROUND = "isReachCapRound";
    /**
     * * The constant RADIUS
     */
    private static final String RADIUS = "radius";
    /**
     * * The constant START_ARC
     */
    private static final String START_ARC = "startArc";
    /**
     * * The constant INNER_BG_COLOR
     */
    private static final String INNER_BG_COLOR = "innerBgColor";
    /**
     * * The constant INNER_PADDING
     */
    private static final String INNER_PADDING = "innerPadding";
    /**
     * * The constant OUTER_COLOR
     */
    private static final String OUTER_COLOR = "outerColor";
    /**
     * * The constant OUTER_SIZE
     */
    private static final String OUTER_SIZE = "outerSize";
    /**
     * 已完成进度条大小
     */
    private int mReachBarSize = Utils.dp2px(getContext(), 2);
    /**
     * 未完成进度条大小
     */
    private int mNormalBarSize = Utils.dp2px(getContext(), 2);
    /**
     * 已完成进度颜色
     */
    private int mReachBarColor = Color.getIntColor("#108ee9");
    /**
     * 未完成进度颜色
     */
    private int mNormalBarColor = Color.getIntColor("#FFD3D6DA");
    /**
     * The constant M background color
     */
    private int mBackgroundColor = Color.WHITE.getValue();
    /**
     * 进度值字体大小
     */
    private int mTextSize = Utils.sp2px(getContext(), 14);
    /**
     * 进度的值字体颜色
     */
    private int mTextColor = Color.getIntColor("#108ee9");
    /**
     * 进度值字体倾斜角度
     */
    private float mTextSkewX;
    /**
     * 进度值后缀
     */
    private String mTextSuffix = "%";
    /**
     * 进度值前缀
     */
    private String mTextPrefix = "";
    /**
     * 是否显示进度值
     */
    private boolean mTextVisible = true;
    /**
     * 画笔是否使用圆角边界，normalStyle下生效
     */
    private boolean mReachCapRound;
    /**
     * 半径
     */
    private int mRadius = Utils.dp2px(getContext(), 20);
    /**
     * 起始角度
     */
    private int mStartArc;
    /**
     * 内部背景填充颜色
     */
    private int mInnerBackgroundColor;
    /**
     * 进度风格
     */
    private int mProgressStyle = PROGRESS_STYLE_NORMAL;
    /**
     * 内部圆与外部圆间距
     */
    private int mInnerPadding = Utils.dp2px(getContext(), 1);
    /**
     * 外部圆环颜色
     */
    private int mOuterColor;
    /**
     * 是否需要绘制内部背景
     */
    private boolean needDrawInnerBackground;
    /**
     * 外部圆环绘制区域
     */
    private RectFloat rectF;
    /**
     * 内部圆环绘制区域
     */
    private RectFloat rectInner;
    /**
     * 外层圆环宽度
     */
    private int mOuterSize = Utils.dp2px(getContext(), 1);
    /**
     * 绘制进度值字体画笔
     */
    private Paint mTextPaint;
    /**
     * 绘制未完成进度画笔
     */
    private Paint mNormalPaint;
    /**
     * 绘制已完成进度画笔
     */
    private Paint mReachPaint;
    /**
     * 内部背景画笔
     */
    private Paint mInnerBackgroundPaint;
    /**
     * 外部圆环画笔
     */
    private Paint mOutPaint;
    /**
     * The constant M real width
     */
    private int mRealWidth;
    /**
     * The constant M real height
     */
    private int mRealHeight;
    /**
     * Upgrade SDK 5 to adapt to the onRefresh and onDraw sequences.
     */
    private boolean mIsOnRefreshed = false;

    /**
     * Circle progress view
     *
     * @param context context
     */
    public CircleProgressView(Context context) {
        this(context, null);
    }

    /**
     * Circle progress view
     *
     * @param context context
     * @param attrs   attrs
     */
    public CircleProgressView(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    /**
     * Circle progress view
     *
     * @param context      context
     * @param attrs        attrs
     * @param defStyleAttr def style attr
     */
    public CircleProgressView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainAttributes(attrs);
        initPaint();
        setLayoutRefreshedListener(this::onRefreshed);
        addDrawTask(this::onDraw);
    }

    /**
     * Set progress value *
     *
     * @param progress progress
     */
    @Override
    public void setProgressValue(int progress) {
        super.setProgressValue(progress);
        invalidate();
    }

    /**
     * On draw *
     *
     * @param component component
     * @param canvas    canvas
     */
    private void onDraw(Component component, Canvas canvas) {
        if (!mIsOnRefreshed) {
            onRefreshed(component);
            mIsOnRefreshed = true;
        }
        switch (mProgressStyle) {
            case PROGRESS_STYLE_NORMAL:
                drawNormalCircle(canvas);
                break;
            case PROGRESS_STYLE_FILL_IN:
                drawFillInCircle(canvas);
                break;
            case PROGRESS_STYLE_FILL_IN_ARC:
                drawFillInArcCircle(canvas);
                break;
        }
    }


    /**
     * On refreshed *
     *
     * @param component component
     */
    private void onRefreshed(Component component) {
        mRealWidth = component.getWidth();
        mRealHeight = component.getHeight();
        Element backgroundElement = getBackgroundElement();
        if (backgroundElement != null) {
            if (backgroundElement instanceof ShapeElement) {
                RgbColor[] rgbColors = ((ShapeElement) backgroundElement).getRgbColors();
                mBackgroundColor = rgbColors[0].asArgbInt();
            }
        }
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        mTextPaint = new Paint();
        mTextPaint.setColor(new Color(mTextColor));
        mTextPaint.setStyle(Paint.Style.FILL_STYLE);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setAntiAlias(true); // 抗锯齿

        mNormalPaint = new Paint();
        mNormalPaint.setColor(new Color(mNormalBarColor));
        mNormalPaint.setStyle(
                mProgressStyle == PROGRESS_STYLE_FILL_IN_ARC ? Paint.Style.FILL_STYLE : Paint.Style.STROKE_STYLE);
        mNormalPaint.setAntiAlias(true);
        mNormalPaint.setStrokeWidth(mNormalBarSize);

        mReachPaint = new Paint();
        mReachPaint.setColor(new Color(mReachBarColor));
        mReachPaint.setStyle(
                mProgressStyle == PROGRESS_STYLE_FILL_IN_ARC ? Paint.Style.FILL_STYLE : Paint.Style.STROKE_STYLE);
        mReachPaint.setAntiAlias(true);
        mReachPaint.setStrokeCap(mReachCapRound ? Paint.StrokeCap.ROUND_CAP : Paint.StrokeCap.BUTT_CAP);
        mReachPaint.setStrokeWidth(mReachBarSize);

        if (needDrawInnerBackground) {
            mInnerBackgroundPaint = new Paint();
            mInnerBackgroundPaint.setStyle(Paint.Style.FILL_STYLE);
            mInnerBackgroundPaint.setAntiAlias(true);
            mInnerBackgroundPaint.setColor(new Color(mInnerBackgroundColor));
        }
        if (mProgressStyle == PROGRESS_STYLE_FILL_IN_ARC) {
            mOutPaint = new Paint();
            mOutPaint.setStyle(Paint.Style.STROKE_STYLE);
            mOutPaint.setColor(new Color(mOuterColor));
            mOutPaint.setStrokeWidth(mOuterSize);
            mOutPaint.setAntiAlias(true);
        }
    }

    /**
     * Obtain attributes *
     *
     * @param attrs attrs
     */
    private void obtainAttributes(AttrSet attrs) {
        mProgressStyle = AttrUtils.getIntFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSSTYLE, PROGRESS_STYLE_NORMAL);
        // 获取三种风格通用的属性
        mNormalBarSize = AttrUtils.getDimensionFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSNORMALSIZE, mNormalBarSize);
        mNormalBarColor = AttrUtils.getColorFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSNORMALCOLOR, mNormalBarColor);
        mReachBarSize = AttrUtils.getDimensionFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSREACHSIZE, mReachBarSize);
        mReachBarColor = AttrUtils.getColorFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSREACHCOLOR, mReachBarColor);
        mTextSize = (int) AttrUtils.getDimensionFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSTEXTSIZE, mTextSize);
        mTextColor = AttrUtils.getColorFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSTEXTCOLOR, mTextColor);
        mTextSkewX = AttrUtils.getDimensionFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSTEXTSKEWX, 0);
        mTextSuffix = AttrUtils.getStringFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSTEXTSUFFIX, mTextSuffix);
        mTextPrefix = AttrUtils.getStringFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSTEXTPREFIX, mTextPrefix);
        mTextVisible = AttrUtils.getBooleanFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSTEXTVISIBLE, mTextVisible);
        mRadius = (int) AttrUtils.getDimensionFromAttr(attrs, CIRCLEPROGRESSVIEW_RADIUS, mRadius);
        rectF = new RectFloat(-mRadius, -mRadius, mRadius, mRadius);

        switch (mProgressStyle) {
            case PROGRESS_STYLE_FILL_IN:
                mReachBarSize = 0;
                mNormalBarSize = 0;
                mOuterSize = 0;
                break;
            case PROGRESS_STYLE_FILL_IN_ARC:
                mStartArc = AttrUtils.getIntFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSSTARTARC, 0) + 270;
                mInnerPadding =
                        (int) AttrUtils.getDimensionFromAttr(attrs, CIRCLEPROGRESSVIEW_INNERPADDING, mInnerPadding);
                mOuterColor = AttrUtils.getColorFromAttr(attrs, CIRCLEPROGRESSVIEW_OUTERCOLOR, mReachBarColor);
                mOuterSize = (int) AttrUtils.getDimensionFromAttr(attrs, CIRCLEPROGRESSVIEW_OUTERSIZE, mOuterSize);
                mReachBarSize = 0; // 将画笔大小重置为0
                mNormalBarSize = 0;
                if (attrs.getAttr(CIRCLEPROGRESSVIEW_PROGRESSNORMALCOLOR).isPresent() && attrs.getAttr(CIRCLEPROGRESSVIEW_PROGRESSNORMALCOLOR).get() != null) {
                    mNormalBarColor = mNormalBarColor;
                } else {
                    mNormalBarColor = Color.TRANSPARENT.getValue();
                }
                int mInnerRadius = mRadius - mOuterSize / 2 - mInnerPadding;
                rectInner = new RectFloat(-mInnerRadius, -mInnerRadius, mInnerRadius, mInnerRadius);

                break;
            case PROGRESS_STYLE_NORMAL:
                mReachCapRound = AttrUtils.getBooleanFromAttr(attrs, CIRCLEPROGRESSVIEW_REACHCAPROUND, true);
                mStartArc = AttrUtils.getIntFromAttr(attrs, CIRCLEPROGRESSVIEW_PROGRESSSTARTARC, 0) + 270;
                if (attrs.getAttr(CIRCLEPROGRESSVIEW_INNERBACKGROUNDCOLOR).isPresent()
                        && attrs.getAttr(CIRCLEPROGRESSVIEW_INNERBACKGROUNDCOLOR).get() != null) {
                    mInnerBackgroundColor = AttrUtils.getColorFromAttr(attrs, CIRCLEPROGRESSVIEW_INNERBACKGROUNDCOLOR,
                            Color.argb(0, 0, 0, 0));
                    needDrawInnerBackground = true;
                }
                break;
        }
    }

    /**
     * 绘制PROGRESS_STYLE_FILL_IN_ARC圆形
     *
     * @param canvas canvas
     */
    private void drawFillInArcCircle(Canvas canvas) {
        canvas.save();
        canvas.drawColor(mBackgroundColor, Canvas.PorterDuffMode.SRC);
        canvas.translate(mRealWidth / 2, mRealHeight / 2);
        // 绘制外层圆环
        canvas.drawArc(rectF, new Arc(0, 360, false), mOutPaint);
        // 绘制内层进度实心圆弧
        // 内层圆弧半径
        float reachArc = getProgress() * 1.0f / getMax() * 360;
        canvas.drawArc(rectInner, new Arc(mStartArc, reachArc, true), mReachPaint);

        // 绘制未到达进度
        if (reachArc != 360) {
            canvas.drawArc(rectInner, new Arc(reachArc + mStartArc, 360 - reachArc, true), mNormalPaint);
        }

        canvas.restore();
    }

    /**
     * 绘制PROGRESS_STYLE_FILL_IN圆形
     *
     * @param canvas canvas
     */
    private void drawFillInCircle(Canvas canvas) {
        canvas.save();
        canvas.drawColor(mBackgroundColor, Canvas.PorterDuffMode.SRC);
        canvas.translate(mRealWidth / 2, mRealHeight / 2);
        float progressY = getProgress() * 1.0f / getMax() * (mRadius * 2);
        float angle = (float) (Math.acos((mRadius - progressY) / mRadius) * 180 / Math.PI);
        float startAngle = 90 + angle;
        float sweepAngle = 360 - angle * 2;
        // 绘制未到达区域
        rectF = new RectFloat(-mRadius, -mRadius, mRadius, mRadius);
        mNormalPaint.setStyle(Paint.Style.FILL_STYLE);
        canvas.drawArc(rectF, new Arc(startAngle, sweepAngle, false), mNormalPaint);
        // 翻转180度绘制已到达区域
        canvas.rotate(180, 0, 0);
        mReachPaint.setStyle(Paint.Style.FILL_STYLE);
        canvas.drawArc(rectF, new Arc(270 - angle, angle * 2, false), mReachPaint);
        // 文字显示在最上层最后绘制
        canvas.rotate(180, 0, 0);
        // 绘制文字
        if (mTextVisible) {
            String text = mTextPrefix + getProgress() + mTextSuffix;
            float textWidth = mTextPaint.measureText(text);
            float textHeight = (mTextPaint.descent() + mTextPaint.ascent());
            canvas.drawText(mTextPaint, text, -textWidth / 2, -textHeight / 2);
        }
        canvas.restore();
    }

    /**
     * 绘制PROGRESS_STYLE_NORMAL圆形
     *
     * @param canvas canvas
     */
    private void drawNormalCircle(Canvas canvas) {
        canvas.save();
        canvas.drawColor(mBackgroundColor, Canvas.PorterDuffMode.SRC);
        canvas.translate(mRealWidth / 2, mRealHeight / 2);
        // 绘制内部圆形背景色
        if (needDrawInnerBackground) {
            canvas.drawCircle(0, 0, mRadius - Math.min(mReachBarSize, mNormalBarSize) / 2,
                    mInnerBackgroundPaint);
        }
        // 绘制文字
        if (mTextVisible) {
            String text = mTextPrefix + getProgress() + mTextSuffix;
            float textWidth = mTextPaint.measureText(text);
            float textHeight = (mTextPaint.descent() + mTextPaint.ascent());
            canvas.drawText(mTextPaint, text, -textWidth / 2, -textHeight / 2);
        }
        // 计算进度值
        float reachArc = getProgress() * 1.0f / getMax() * 360;
        // 绘制未到达进度
        if (reachArc != 360) {
            canvas.drawArc(rectF, new Arc(reachArc + mStartArc, 360 - reachArc, false), mNormalPaint);
        }
        // 绘制已到达进度
        canvas.drawArc(rectF, new Arc(mStartArc, reachArc, false), mReachPaint);
        canvas.restore();
    }

    /**
     * 动画进度(0-当前进度)
     *
     * @param duration 动画时长
     */
    public void runProgressAnim(long duration) {
        setProgressInTime(0, duration);
    }

    /**
     * Set progress in time *
     *
     * @param progress 进度值
     * @param duration 动画播放时间
     */
    public void setProgressInTime(final int progress, final long duration) {
        setProgressInTime(progress, getProgress(), duration);
    }

    /**
     * Set progress in time *
     *
     * @param startProgress 起始进度
     * @param progress      进度值
     * @param duration      动画播放时间
     */
    public void setProgressInTime(int startProgress, final int progress, final long duration) {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(startProgress, progress);
        valueAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float value) {
                setProgressValue((int) value);
            }
        });

        valueAnimator.setInterpolator(Animator.CurveType.ACCELERATE_DECELERATE);
        valueAnimator.setDuration(duration);
        valueAnimator.start();
    }

    /**
     * Get reach bar size int
     *
     * @return the int
     */
    public int getReachBarSize() {
        return mReachBarSize;
    }

    /**
     * Set reach bar size *
     *
     * @param reachBarSize reach bar size
     */
    public void setReachBarSize(int reachBarSize) {
        mReachBarSize = Utils.dp2px(getContext(), reachBarSize);
        invalidate();
    }

    /**
     * Get normal bar size int
     *
     * @return the int
     */
    public int getNormalBarSize() {
        return mNormalBarSize;
    }

    /**
     * Set normal bar size *
     *
     * @param normalBarSize normal bar size
     */
    public void setNormalBarSize(int normalBarSize) {
        mNormalBarSize = Utils.dp2px(getContext(), normalBarSize);
        invalidate();
    }

    /**
     * Get reach bar color int
     *
     * @return the int
     */
    public int getReachBarColor() {
        return mReachBarColor;
    }

    /**
     * Set reach bar color *
     *
     * @param reachBarColor reach bar color
     */
    public void setReachBarColor(int reachBarColor) {
        mReachBarColor = reachBarColor;
        invalidate();
    }

    /**
     * Get normal bar color int
     *
     * @return the int
     */
    public int getNormalBarColor() {
        return mNormalBarColor;
    }

    /**
     * Set normal bar color *
     *
     * @param normalBarColor normal bar color
     */
    public void setNormalBarColor(int normalBarColor) {
        mNormalBarColor = normalBarColor;
        invalidate();
    }

    /**
     * Get text size int
     *
     * @return the int
     */
    public int getTextSize() {
        return mTextSize;
    }

    /**
     * Set text size *
     *
     * @param textSize text size
     */
    public void setTextSize(int textSize) {
        mTextSize = Utils.sp2px(getContext(), textSize);
        invalidate();
    }

    /**
     * Get text color int
     *
     * @return the int
     */
    public int getTextColor() {
        return mTextColor;
    }

    /**
     * Set text color *
     *
     * @param textColor text color
     */
    public void setTextColor(int textColor) {
        mTextColor = textColor;
        invalidate();
    }

    /**
     * Get text skew x float
     *
     * @return the float
     */
    public float getTextSkewX() {
        return mTextSkewX;
    }

    /**
     * Set text skew x *
     *
     * @param textSkewX text skew x
     */
    public void setTextSkewX(float textSkewX) {
        mTextSkewX = textSkewX;
        invalidate();
    }

    /**
     * Get text suffix string
     *
     * @return the string
     */
    public String getTextSuffix() {
        return mTextSuffix;
    }

    /**
     * Set text suffix *
     *
     * @param textSuffix text suffix
     */
    public void setTextSuffix(String textSuffix) {
        mTextSuffix = textSuffix;
        invalidate();
    }

    /**
     * Get text prefix string
     *
     * @return the string
     */
    public String getTextPrefix() {
        return mTextPrefix;
    }

    /**
     * Set text prefix *
     *
     * @param textPrefix text prefix
     */
    public void setTextPrefix(String textPrefix) {
        mTextPrefix = textPrefix;
        invalidate();
    }

    /**
     * Is text visible boolean
     *
     * @return the boolean
     */
    public boolean isTextVisible() {
        return mTextVisible;
    }

    /**
     * Set text visible *
     *
     * @param textVisible text visible
     */
    public void setTextVisible(boolean textVisible) {
        mTextVisible = textVisible;
        invalidate();
    }

    /**
     * Is reach cap round boolean
     *
     * @return the boolean
     */
    public boolean isReachCapRound() {
        return mReachCapRound;
    }

    /**
     * Set reach cap round *
     *
     * @param reachCapRound reach cap round
     */
    public void setReachCapRound(boolean reachCapRound) {
        mReachCapRound = reachCapRound;
        invalidate();
    }

    /**
     * Get radius int
     *
     * @return the int
     */
    public int getRadius() {
        return mRadius;
    }

    /**
     * Set radius *
     *
     * @param radius radius
     */
    public void setRadius(int radius) {
        mRadius = Utils.dp2px(getContext(), radius);
        invalidate();
    }

    /**
     * Get start arc int
     *
     * @return the int
     */
    public int getStartArc() {
        return mStartArc;
    }

    /**
     * Set start arc *
     *
     * @param startArc start arc
     */
    public void setStartArc(int startArc) {
        mStartArc = startArc;
        invalidate();
    }

    /**
     * Get inner background color int
     *
     * @return the int
     */
    public int getInnerBackgroundColor() {
        return mInnerBackgroundColor;
    }

    /**
     * Set inner background color *
     *
     * @param innerBackgroundColor inner background color
     */
    public void setInnerBackgroundColor(int innerBackgroundColor) {
        mInnerBackgroundColor = innerBackgroundColor;
        invalidate();
    }

    /**
     * Get progress style int
     *
     * @return the int
     */
    public int getProgressStyle() {
        return mProgressStyle;
    }

    /**
     * Set progress style *
     *
     * @param progressStyle progress style
     */
    public void setProgressStyle(int progressStyle) {
        mProgressStyle = progressStyle;
        invalidate();
    }

    /**
     * Get inner padding int
     *
     * @return the int
     */
    public int getInnerPadding() {
        return mInnerPadding;
    }

    /**
     * Set inner padding *
     *
     * @param innerPadding inner padding
     */
    public void setInnerPadding(int innerPadding) {
        mInnerPadding = Utils.dp2px(getContext(), innerPadding);
        int mInnerRadius = mRadius - mOuterSize / 2 - mInnerPadding;
        rectInner = new RectFloat(-mInnerRadius, -mInnerRadius, mInnerRadius, mInnerRadius);
        invalidate();
    }

    /**
     * Get outer color int
     *
     * @return the int
     */
    public int getOuterColor() {
        return mOuterColor;
    }

    /**
     * Set outer color *
     *
     * @param outerColor outer color
     */
    public void setOuterColor(int outerColor) {
        mOuterColor = outerColor;
        invalidate();
    }

    /**
     * Get outer size int
     *
     * @return the int
     */
    public int getOuterSize() {
        return mOuterSize;
    }

    /**
     * Set outer size *
     *
     * @param outerSize outer size
     */
    public void setOuterSize(int outerSize) {
        mOuterSize = Utils.dp2px(getContext(), outerSize);
        invalidate();
    }

    /**
     * Invalidate
     */
    @Override
    public void invalidate() {
        initPaint();
        super.invalidate();
    }

    /**
     * Progress style    @IntDef({PROGRESS_STYLE_NORMAL, PROGRESS_STYLE_FILL_IN,
     * PROGRESS_STYLE_FILL_IN_ARC})
     */
    @Retention(RetentionPolicy.SOURCE)
    public @interface ProgressStyle {

    }
}
